<template>
<div>
    <common-loading :loading="loading" :loadingText="loadingText" :size="loadingSize" :textColor="loadingTextColor">
        <i slot="loadingIcon" class="el-icon-loading"></i>
    </common-loading>
    <canvas
      v-show="!loading"
      :id="canvasId"
      :class="{'canvas':canDraw}"
      :width="width"
      :height="height"
      :style="{'width':`${width}px`,'height':`${height}px`}"
      @mousedown="canvasDown($event)"
      @mouseup="canvasUp($event)"
      @mousemove="canvasMove($event)"
      @touchstart="canvasDown($event)"
      @touchend="canvasUp($event)"
      @touchmove="canvasMove($event)"
      >
    </canvas>
    <el-select v-if="!loading" placeholder="请选择画图类型" v-model="lineType" class="selectItem" @change="handleChange">
        <el-option label="点" value="point"></el-option>
        <el-option label="矩形" value="rec"></el-option>
        <el-option label="圆形" value="circle"></el-option>
    </el-select>
    <el-button v-if="isDraw" class="button" icon="el-icon-back" @click="clean">清空画布</el-button>
    <el-button v-if="isDraw" class="button completeBtn" type="primary" icon="el-icon-check" @click="handleComplete">保存绘制</el-button>
</div>
      
</template>
<script>
  import CommonLoading from "../components/CommonLoading.vue"
  export default {
    components:{
      CommonLoading
    },
    props: {
      canvasId:{
        type: String,
        required: true
      },
      show:{
        type: Boolean,
        default: false
      },
      canDraw: { // 是否可以绘制
        type: Boolean,
        default: true
      },
      url: { // 图片路径
        type: String,
        required: true
      },
      info: { // 位置点信息
        type: Array
      },
      width: { // 绘图区域宽度
        type: Number,
        required: true
      },
      height: { // 绘图区域高度
        type: Number,
        required: true
      },
      lineColor: { // 画笔颜色
        type: String,
        default: '#0095DA'
      },
      lineWidth: { // 画笔宽度
        type: Number,
        default: 2
      },
      loadingText:{
        type: String,
        default:'正在渲染...'
      },
      loadingSize:{
        type: String,
        default:'normal'
      },
      loadingTextColor:{
        type: String,
        default:'#333'
      }
    },
    watch: {
      info (val) {
        if (val) {
          this.initDraw()
        }
      },
      show(val){
        if(val){
          this.initDraw()
        }else{
          this.destoryDraw()
        }
      }
    },
    data () {
      return {
        loading:false,
        isDraw:false,
        // 同一页面多次渲染时，用于区分元素的id
        // radom: uuid.v4(),
        radom:'canvas',
        // canvas对象
        context: {},
        // 是否处于绘制状态
        canvasMoveUse: false,
        // 绘制矩形和椭圆时用来保存起始点信息
        beginRec: {
          x: '',
          y: '',
          imageData: ''
        },
        // 储存坐标信息
        drawInfo: [],
        lineType:'point',
        // 背景图片缓存
        img: new Image()
      }
    },
    methods: {
      destoryDraw(){
        this.isDraw = false
        this.loading = false
        this.canvas = null
        this.context = null
        this.img = null
        this.lineType = "point"
      },
      // 初始化绘制信息
      initDraw () {
        // 初始化画布
        this.canvas = document.getElementById(this.canvasId)
        if(!this.canvas.getContext){
            this.$message({
                type: 'warning',
                message: '该浏览器不支持绘制mask!'
            })
            this.$emit("renderError",true)
            return false
        }
        this.context = this.canvas.getContext('2d')
        this.initStyle()
        this.initImage()
      },
      initStyle(){
        // 初始化画笔
        this.context.lineWidth = this.lineWidth
        this.context.strokeStyle = this.lineColor
      },
      initImage(){
        // 初始化背景图片
        this.loading = true;
        this.img = new Image()
        this.img.setAttribute('crossOrigin', 'Anonymous')
        this.img.src = this.url
        // console.log(this.img.src)
        this.img.onerror = () => {
          this.$emit("renderError",true)
        }
        this.img.onload = () => {
            if(this.clean()){
              this.$emit("renderError",false)   
              setTimeout(()=>{
                this.loading = false
              },500)
            }else{
              this.$emit("renderError",true)   
              this.loading = false
            }
                   
        } 
      },
      // 鼠标按下
      canvasDown (e) {
        if (this.canDraw) {
          this.initStyle()
          this.canvasMoveUse = true
          // client是基于整个页面的坐标
          let eleinfo = this.windowToCanvas(this.canvas,e.clientX,e.clientY)
          // 记录起始点和起始状态
          this.beginRec.x = eleinfo.x
          this.beginRec.y = eleinfo.y
          this.beginRec.imageData = this.context.getImageData(0, 0, this.width, this.height)
          // 存储本次绘制坐标信息
          this.drawInfo.push({
            x: eleinfo.x / this.width,
            y: eleinfo.y / this.height,
            type: this.lineType
          })
          if (this.lineType === 'line'){
              this.context.moveTo(this.beginRec.x, this.beginRec.y) //把画笔移动到指定的坐标
          }else if(this.lineType === 'point'){   
              this.canvasMoveUse = false
              this.drawPoint(this.context,eleinfo.x,eleinfo.y)
              if(this.drawInfo.length>=2){
                let drawinfo = JSON.parse(JSON.stringify(this.drawInfo))
                let preX = drawinfo[drawinfo.length-2].x * this.width
                let preY = drawinfo[drawinfo.length-2].y * this.height
                this.drawLine(this.context,preX,preY,eleinfo.x,eleinfo.y)
              }
          }
        }
      },
      // 根据坐标信息绘制图形
      drawWithInfo () {
        this.info.forEach(item => {
          this.context.beginPath()
          if (!item.type) {
            // 设置颜色
            this.context.strokeStyle = item.regionColor
            this.context.fillStyle = item.regionColor
            // 绘制多边形的边
            if (typeof item.region === 'string') {
              item.region = JSON.parse(item.region)
            }
            item.region.forEach(point => {
              this.context.lineTo(point.x * this.width, point.y * this.height)
            })
            this.context.closePath()
          } else if (item.type === 'rec') {
            this.context.rect(item.x * this.width, item.y * this.height, item.w * this.width, item.h * this.height)
          } else if (item.type === 'circle') {
            this.drawEllipse(this.context, (item.x + item.a) * this.width, (item.y + item.b) * this.height, item.a > 0 ? item.a * this.width : -item.a * this.width, item.b > 0 ? item.b * this.height : -item.b * this.height)
          }
          this.context.stroke()
        })
      },
      // 鼠标移动时绘制
      canvasMove (e) {
        if (this.canvasMoveUse && this.canDraw) {
          let eleinfo = this.windowToCanvas(this.canvas,e.clientX,e.clientY)
          if (this.lineType === 'rec') { // 绘制矩形时恢复起始点状态再重新绘制
            this.context.putImageData(this.beginRec.imageData, 0, 0)
            this.context.beginPath()
            this.context.rect(this.beginRec.x, this.beginRec.y, eleinfo.x - this.beginRec.x, eleinfo.y - this.beginRec.y)
            let drawinfo = this.drawInfo[this.drawInfo.length - 1]
            drawinfo.w = eleinfo.x / this.width - drawinfo.x  //数据双向绑定，同时改变this.drawInfo[this.drawInfo.length - 1]的值
            drawinfo.h = eleinfo.y / this.height - drawinfo.y
          } else if (this.lineType === 'circle') { // 绘制椭圆时恢复起始点状态再重新绘制
            this.context.putImageData(this.beginRec.imageData, 0, 0)
            this.context.beginPath()
            let a = (eleinfo.x - this.beginRec.x) / 2
            let b = (eleinfo.y - this.beginRec.y) / 2
            this.drawEllipse(this.context, this.beginRec.x + a, this.beginRec.y + b, a > 0 ? a : -a, b > 0 ? b : -b)
            let drawinfo = this.drawInfo[this.drawInfo.length - 1]
            drawinfo.a = a / this.width
            drawinfo.b = b / this.height
          }else{
            //   this.context.putImageData(this.beginRec.imageData, 0, 0)
              // this.context.beginPath()
              this.context.lineTo(eleinfo.x, eleinfo.y) //绘制一条从当前位置到指定坐标的直线.
              // this.context.closePath()
          }
          this.context.stroke()
        }
      },
      // 绘制椭圆
      drawEllipse (context, x, y, a, b) {
        context.save()
        var r = (a > b) ? a : b
        var ratioX = a / r
        var ratioY = b / r
        context.scale(ratioX, ratioY)
        context.beginPath()
        context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI, false)
        context.closePath()
        context.restore()
      },
      // 绘制点
      drawPoint(context, x, y){
        context.beginPath()
        context.arc(this.beginRec.x, this.beginRec.y, 2, 0, Math.PI*2, false)
        context.fillStyle="rgba(255,255,255,1)"
        context.fill()
        context.closePath()
        context.stroke()
      },
      drawLine(context, startX, startY, endX, endY){
        context.moveTo(startX, startY)
        context.lineTo(endX, endY)
        context.stroke()
      },
      windowToCanvas(canvas, x, y){
        let rect = canvas.getBoundingClientRect()
        return {
            'x': x - rect.left * (canvas.width/rect.width),
            'y': y - rect.top * (canvas.height/rect.height)
        }
      },
      // 鼠标抬起
      canvasUp (e) {
        if (this.canDraw) {
          this.isDraw = true
          this.canvasMoveUse = false
        }
      },
      // 获取坐标信息
      getInfo () {
        return this.drawInfo
      },
      // 清空画布
      clean () {
        this.drawInfo = []
        try {
          // console.log(this.context)
          this.context.drawImage(this.img, 0, 0, this.width, this.height)
          return true
        } catch (error) {
          console.log(error)
          return false
        }
        // if (this.info && this.info.length !== 0) this.drawWithInfo()
      },
      handleComplete(){
        let info = JSON.parse(JSON.stringify(this.getInfo()));
        this.$emit("CanvasComplete",info);
      },
      handleChange(val){
        this.lineType = val
        this.clean()
      }
    }
  }
</script>
<style lang="scss" scoped>
  .canvas{
    cursor: crosshair;
  }
  .selectItem{
    width: 20%;
    margin-right: 10px;
  }  
</style>
